import React, { Component } from 'react'
import { Alert, Button, Input, message, Select, Spin } from 'antd'
import { connect } from '@umijs/max'
import _ from 'lodash'
import FieldMapping from 'react-field-mapping'
import { v4 } from 'uuid'
import styles from './index.less'

const sourceCols = [
  { title: '源字段', key: 'fieldName' },
  { title: '类型', key: 'fieldType' },
  // { title: '描述', key: 'fieldDesc' },
]

@connect(({ offlineHttpsApiCreate }) => ({ ...offlineHttpsApiCreate }))
class FieldMap extends Component {
  constructor(props) {
    super(props)
    this.state = {
      relation: [],
      fieldMapType: null,
      type: {
        Kafka: [
          'string',
          'boolean',
          'double',
          'date',
          'bytes',
        ],
        Mongodb: [
          'String',
          'Boolean',
          'Integer',
          'Double',
          'Arrays',
          'Object',
          'Null',
          'Timestamp',
          'Date',
        ],
        HBase: [
          'String',
          'BinaryString',
          'Int',
          'Short',
          'Long',
          'Boolean',
          'Double',
          'Float',
          'Date',
        ],
      },
      sourceFields: [],
      targetFields: [],
      spinning: false,
    }
  }

  componentDidMount() {
    this.initOperate()
  }

  UNSAFE_componentWillReceiveProps(nextProps, nextContext) {
    this.initOperate()
  }

  initOperate = () => {
    const { formData } = this.props
    const {
      targetFields, targetDsType, isGoBack, nodeId,
    } = formData || {}
    // 上一步退回、编辑 Mongodb、HBase、Kafka
    if ((nodeId || isGoBack) && (targetDsType === 'Mongodb' || targetDsType === 'HBase' || targetDsType === 'Kafka')) {
      this.handleMappingData(targetFields)
    } else {
      this.queryGetTagetTableFields()
    }
  }

  // 获取关联映射字段
  queryGetTagetTableFields = () => {
    const { formData } = this.props
    const {
      targetDsId, targetTableName,
    } = formData || {}
    this.setState({
      spinning: true,
    })

    this.props.dispatch({
      type: 'offlineHttpsApiCreate/queryGetTagetTableFields',
      params: {
        dsId: targetDsId,
        tableName: targetTableName,
      },
      cb: (res) => {
        this.handleMappingData(res?.fields)
      },
    })
  }

  handleMappingData = (fieldList) => {
    const { formData } = this.props
    const {
      tablePreviewColumnArray, fieldMapType, targetDsType, isChangeTargetTable,
    } = formData || {}
    const sourceFields = []
    tablePreviewColumnArray?.map(item => {
      sourceFields.push({
        isPk: null,
        fieldName: item,
        key: item,
        fieldType: null,
      })
      return null
    })

    // 剔除编辑后 tablePreviewColumnArray 里的内容减少
    const filterRelation = []
    formData?.relation?.map(item => {
      if (tablePreviewColumnArray?.indexOf(item?.source?.fieldName) !== -1) {
        filterRelation.push(item)
      }
      return null
    })

    const targetFields = []
    const fieldListCopy = _.cloneDeep(fieldList)

    fieldListCopy?.map((obj) => {
      obj.key = obj?.fieldName
      filterRelation?.map((o) => {
        if (o.fieldName === obj.fieldName) {
          o.target.isPk = !!obj.isPk
        }
        return null
      })
      targetFields.push(obj)
      return null
    })

    sourceFields.sort((a, b) => (`${a?.fieldName}`).localeCompare(`${b?.fieldName}`))

    this.setState(
      {
        sourceFields,
        targetFields,
        fieldMapType: isChangeTargetTable ? null : fieldMapType,
        targetDsType,
        spinning: false,
      },
      () => {
        // 注意此处要深拷贝一份
        // const relationCopy = _.cloneDeep(formData?.relation)
        const relationCopy = _.cloneDeep(filterRelation)
        this.setState({
          relation: isChangeTargetTable ? [] : (relationCopy || []),
        })
      },
    )
  }

  // 同行映射
  sameLine = () => {
    const { sourceFields, targetFields } = this.state
    const len = sourceFields.length > targetFields.length
      ? targetFields.length
      : sourceFields.length
    const relation = []
    for (let i = 0; i < len; i++) {
      relation.push({
        source: {
          ...sourceFields[i],
        },
        target: {
          ...targetFields[i],
        },
      })
    }

    this.setState({
      relation,
      fieldMapType: 0,
    })
  }

  // 同名映射
  sameName = () => {
    const { sourceFields, targetFields } = this.state
    const relation = []
    sourceFields.map((item) => {
      targetFields.map((n) => {
        if (item.key.toLowerCase() === n.key.toLowerCase()) {
          relation.push({
            source: {
              ...item,
            },
            target: {
              ...n,
            },
          })
        }
        return null
      })
      return null
    })

    this.setState({
      relation,
      fieldMapType: 1,
    })
  }

  // 上一步按钮回调
  preStep = () => {
    const { relation, fieldMapType, targetFields } = this.state

    const formDataTemp = {
      ...this.props.formData,
      relation,
      fieldMapType,
      isGoBack: true,
      targetFields,
    }
    this.props.setFormDataFn(formDataTemp)
    this.props.changeStep(1)
  }

  // 下一步按钮回调
  nextStep = () => {
    const { relation, fieldMapType, targetFields } = this.state
    if (relation?.length) {
      const sourceFields = []
      relation.map((obj) => {
        sourceFields.push(obj.source)
        return null
      })

      const fieldMappings = []
      relation?.map((item) => {
        fieldMappings.push({
          isSourceFieldPk: item.source.isPk,
          isTargetFieldPk: item.target.isPk,
          sourceField: item.source.fieldName,
          sourceFieldType: item.source.fieldType,
          targetField: item.target.fieldName,
          targetFieldType: item.target.fieldType,
        })
        return null
      })

      const formDataTemp = {
        ...this.props.formData,
        relation,
        sourceFields,
        fieldMappings,
        fieldMapType, // 后端加一个字段
        targetFields,
        isChangeTargetTable: false, // 重置 isChangeTargetTable 的值
      }
      this.props.setFormDataFn(formDataTemp)

      this.props.changeStep(3)
    } else {
      message.warning('字段映射不能为空')
    }
  };

  onConfirm = () => {
    const { relation, fieldMapType, targetFields } = this.state
    if (relation?.length) {
      const sourceFields = []
      relation.map((obj) => {
        sourceFields.push(obj.source)
        return null
      })

      const fieldMappings = []
      relation?.map((item) => {
        fieldMappings.push({
          isSourceFieldPk: item.source.isPk,
          isTargetFieldPk: item.target.isPk,
          sourceField: item.source.fieldName,
          sourceFieldType: item.source.fieldType,
          targetField: item.target.fieldName,
          targetFieldType: item.target.fieldType,
        })
        return null
      })

      const formDataTemp = {
        ...this.props.formData,
        relation,
        sourceFields,
        fieldMappings,
        fieldMapType, // 后端加一个字段
        targetFields,
        isChangeTargetTable: false, // 重置 isChangeTargetTable 的值
      }
      this.props.setFormDataFn(formDataTemp)
      this.offlineSave(formDataTemp)
    } else {
      message.warning('字段映射不能为空')
    }
  }

  offlineSave = (formData) => {
    const { taskNode } = this.props
    const { id: nodeId, name } = taskNode || {}

    const {
      apiHttpRequest, previewExpressRequest, taskName, targetDsId, targetDsType, targetTableName,
      errorNumLimit, isTruncate, fieldMappings, fieldMapType, id, targetFields,
    } = formData

    const isEdit = id ? { id } : {}

    const params = {
      ...isEdit,
      nodeId,
      nodeName: name,
      apiHttpRequest,
      previewExpressRequest,
      taskName,
      taskConfigRequest: {
        targetDsId,
        targetDsType,
        targetTableName,
        errorNumLimit: errorNumLimit || 0,
        isTruncate: isTruncate ? 1 : 0,
        fieldMappings,
        fieldMapType,
        dataReplaceRuleId: 8, // 后端约定固定的值
        targetFields,
      },
    }

    this.setState({
      spinning: true,
    })

    this.props.dispatch({
      type: 'offlineHttpsApiCreate/querySaveTask',
      params,
      cb: (res) => {
        const { status, msg } = res
        this.setState({
          spinning: false,
        })
        if (status === 200) {
          message.success('操作成功')

          const taskConfigRequest = params.taskConfigRequest

          const formDataTemp = {
            ...formData,
            nodeId,
            nodeName: name,
            apiHttpRequest,
            previewExpressRequest,
            taskName,
            isGoBack: true,
            isView: true,
            ...taskConfigRequest,
          }

          this.props.setFormDataFn(formDataTemp)
        } else {
          message.error(msg || '服务端错误')
        }
      },
    })
  }

  render() {
    const { isView } = this.props.formData
    const {
      relation, fieldMapType, sourceFields, targetFields, spinning, targetDsType, type,
    } = this.state

    const targetColsEdit = [
      {
        title: '源字段',
        key: 'fieldName',
        render: (val, record, k) => (
          <div>
            {record.edit ? (
              <Input
                maxLength={256}
                value={val}
                style={{ width: '100%' }}
                onChange={(e) => {
                  relation.map((obj) => {
                    if (obj.source.key === record.key) {
                      obj.source.fieldName = e.target.value
                      obj.source.key = e.target.value
                    }
                    return null
                  })
                  record.fieldName = e.target.value
                  record.key = e.target.value
                  this.setState(
                    {
                      targetFields: [...targetFields],
                    },
                    () => {
                      this.setState({
                        relation: [...relation],
                      })
                    },
                  )
                }}
              />
            ) : (
              <span>{val}</span>
            )}
          </div>
        ),
      },
      {
        title: '类型',
        key: 'fieldType',
        render: (val, record, k) => (
          <div>
            {record.edit ? (
              <Select
                value={val}
                style={{ width: '100%' }}
                onChange={(value) => {
                  relation.map((obj) => {
                    if (obj.source.key === record.key) {
                      obj.source.fieldType = value
                    }
                    return null
                  })
                  record.fieldType = value
                  this.setState(
                    {
                      targetFields: [...targetFields],
                    },
                    () => {
                      this.setState({
                        relation: [...relation],
                      })
                    },
                  )
                }}
              >
                {/* {type[sourceDsType].map((v, index) => ( */}
                {type[targetDsType].map((v, index) => (
                  <Select.Option title={v} key={index} value={v}>
                    {v}
                  </Select.Option>
                ))}
              </Select>
            ) : (
              <span>{val}</span>
            )}
          </div>
        ),
      },
      {
        title: '操作',
        key: 'active',
        width: '1rem',
        render: (val, record, k) => (
          <div>
            {record.edit ? (
              <span
                style={{
                  fontSize: '.12rem',
                  marginRight: '.05rem',
                }}
                onClick={() => {
                  if (record.fieldType && record.fieldName) {
                    record.edit = false
                    this.setState({
                      targetFields: [...targetFields],
                    })
                  } else {
                    message.warning('字段名或类型不能为空')
                  }
                }}
                className={isView ? styles.disabled : styles.editBtnColor}
              >
                保存
              </span>
            ) : (
              <span
                style={{
                  fontSize: '.12rem',
                  marginRight: '.08rem',
                }}
                onClick={() => {
                  record.edit = true
                  this.setState({
                    targetFields: [...targetFields],
                  })
                }}
                className={isView ? styles.disabled : styles.editBtnColor}
              >
                编辑
              </span>
            )}
            <span
              style={{
                fontSize: '.12rem',
              }}
              onClick={() => {
                const relations = [...relation]
                relation.map((obj, index) => {
                  if (obj.source.key === record.key) {
                    relations.splice(index, 1)
                  }
                  return null
                })
                const data = [...targetFields]
                data.splice(k, 1)
                this.setState(
                  {
                    targetFields: [...data],
                  },
                  () => {
                    this.setState({
                      relation: [...relations],
                    })
                  },
                )
              }}
              className={isView ? styles.disabled : styles.editBtnColor}
            >
              删除
            </span>
          </div>
        ),
      },
    ]

    return (
      <div className={`${styles.field_map} ${isView ? styles.field_map_detail : ''}`}>
        <div className={styles.column}>字段映射</div>
        {
          !isView && (
            <Alert message="您要配置来源表与目标表的字段映射关系，通过连线将待同步的字段左右相连。也可以通过同行映射、同名映射批量完成映射。" type="info" showIcon />
          )
        }
        <div className={styles.btn_wrap}>
          <span className={`${(fieldMapType === 0 && relation?.length > 0) ? styles.on : ''} ${isView ? styles.disabled : ''}`} onClick={this.sameLine}>同行映射</span>
          <span className={`${(fieldMapType === 1 && relation?.length > 0) ? styles.on : ''} ${isView ? styles.disabled : ''}`} onClick={this.sameName}>同名映射</span>
          {
            relation?.length > 0 && (
              <span
                onClick={() => {
                  this.setState({
                    relation: [],
                    fieldMapType: null,
                  })
                }}
                className={isView ? styles.disabled : ''}
              >
                取消映射
              </span>
            )
          }
          {targetDsType === 'Kafka' || targetDsType === 'Mongodb' || targetDsType === 'HBase' ? (
            <span
              onClick={() => {
                const newSourceFields = [...targetFields]
                newSourceFields.push({
                  edit: true,
                  key: v4(),
                })
                this.setState({
                  targetFields: newSourceFields,
                })
              }}
              className={isView ? styles.disabled : ''}
            >添加目标字段
            </span>
          ) : null}
        </div>
        <div className={styles.field_mapping}>
          <Spin spinning={spinning} tip="正在获取字段信息...">
            <FieldMapping
              {...{
                source: {
                  data: sourceFields,
                  columns: sourceCols,
                  mutiple: false,
                },
                target: {
                  data: targetFields,
                  // columns: sourceCols,
                  columns: (targetDsType === 'Kafka' || targetDsType === 'Mongodb' || targetDsType === 'HBase') ? targetColsEdit : sourceCols,
                  mutiple: false,
                },
                relation,
                edit: !isView,
                onChange: (relations) => {
                  this.setState({
                    relation: relations,
                  })
                },
              }}
            />
          </Spin>
        </div>

        {
          !isView && (
            <div className={styles.edit_footer}>
              {/* <Button */}
              {/*  className={styles.edit_btn} */}
              {/*  onClick={() => { history.push('/dataIntegrate/apiGather/http') }} */}
              {/* > */}
              {/*  取消 */}
              {/* </Button> */}
              <Button
                className={styles.edit_btn}
                type="primary"
                onClick={this.preStep}
              >
                上一步
              </Button>
              <Button 
                loading={spinning} 
                disabled={isView} 
                onClick={this.onConfirm} 
                className={styles.edit_btn} 
                type="primary"
              >
                确认
              </Button>

              {/* <Button
                className={styles.edit_btn}
                type="primary"
                onClick={this.nextStep}
              >
                下一步
              </Button> */}
            </div>
          )
        }
      </div>
    )
  }
}

export default FieldMap
